import os

import Treenode
import requests
import pickle
import json
from pypbc import *


def GenACT():
    Node = Treenode.Node

    ACT = Node('k', 1,0)
    ACT.Root()
    node1 = Node('attr', 1,1)
    node2 = Node('k', 2,2)
    node3 = Node('attr', 2,3)
    node4 = Node('attr', 4,4)
    ACT.appendChild(node1)
    node2.appendChild(node3)
    node2.appendChild(node4)
    ACT.appendChild(node2)

    return ACT


def decUserSK(M, sk):
    # dec message use sk
    return '1'


def Enc(M, gama, PK, pairing):
    # 将M映射到G2
    print('start enc')
    #M = Element.from_hash(pairing, GT, M)  # dont need manual hash,automic get data hash
    s =Element.random(pairing, Zr)

    y=eval(open(os.path.dirname(__file__) + '/../sys/MK.txt').read())['y']
    g=eval(open(os.path.dirname(__file__) + '/../sys/PK.txt').read())['g']
    y=Element(pairing,Zr,value=int(y,16))
    #print('y',y),right

    g=Element(pairing,G1,value=g)
    # pkfile = open('./sys/PK.txt','r')
    # PK = eval(pkfile.read())
    # gs= PK['g']
    # g=Element(pairing,G1,value=gs)

    Y = (pairing.apply(g,g))**y
    print('!Ys:',Y**s)

    E_b = M * (Y ** s)
    E_s = []
    for gi in gama:
        ti = PK['T' + str(gi)]
        Ti = Element(pairing, G1, value=ti)
        E_s.append([Element(pairing, G1, value=Ti ** s), gi])
        #E_s.append([Ti**s,gi])
    print('enc end')
    return [gama, E_b, E_s]


def DEC(E, D, ACT, pairing):
    print('dec start')
    # for di in D:
    #     di[0] = Element(pairing, G1, value=di[0])
    #     print('di to ele',di[0])
    def findindex(D, attr):
        for index in range(len(D)):
            if (D[index][1] == attr):
                return index
        return -1

    def lagrange(i, S, x, pairing):
        print('calc delta for',i)
        res = Element.one(pairing, Zr)
        i = Element(pairing, Zr, value=i)
        x = Element(pairing, Zr, value=x)
        #res = 1
        for n in S:
            j=n[1]
            j=Element(pairing,Zr,value=j)#取得相对索引
            if (i != j):
                print('i',i)
                nume = x.__add__(j.__neg__())
                deno = i.__add__(j.__neg__())
                res = res.__mul__(nume.__mul__(deno.__pow__(-1)))
                # nume = x-j
                # deno = i-j
                # res = res*(nume/deno)

        #res = Element(pairing,Zr,value = int(res))
        return res

    def findLeaf(node):
        if (node.type == 'attr'):
            print(node.value)
            index1 = findindex(D, node.value)
            index2 = findindex(E[2], node.value)
            if (index1!=-1 and index2 !=-1):
                print("Di:",D[index1])
                Di = Element(pairing,G1,value=D[index1][0])
                print(Di)
                #
                print('Ex:',E[2][index2])
                return pairing.apply(Di, E[2][index2][0])  # if i in gama retuen e(dx,ei)
            else:
                return -1  # G2 dedibianjie (zuixiaozhi cankao gelun
        else:
            Sx = []
            index = 0
            for child in node.child:
                if (len(Sx) != child.value):
                    fz = findLeaf(child)
                    if (type(fz) != int):
                        Sx.append([fz,child.index])
                        #Sx.append([fz,index])
                else:
                    break
            print('Sx:',Sx)
        # delta = lagrang vlaue where x =
        # satisfied kx,cacl
            # if(node.isRoot):
            #     return Sx[0]
            if (not (len(Sx) >= node.value)):
                print('fail node')
                return -1
            else:
                fx = Element.one(pairing, GT)
                print('calc fx')
                for n in Sx:
                    #print(f[1])
                    i = n[1] #node index of tree
                    print('node index',i)
                    delta = lagrange(i, Sx, 0, pairing)
                    print('delta',delta)
                    fx = fx.__mul__(n[0].__pow__(delta))
                print('fx',fx)
                return fx

    Ys = findLeaf(ACT)
    return Ys


ppfile = open('./sys/pairingparams.txt', 'r')
params = Parameters(ppfile.read())
pairing = Pairing(params)


ACT = GenACT()
fw = open('./user/ACT.pkl', "wb")
ACT_b = pickle.dump(ACT, fw)
fw.seek(0)
print(ACT.child[1].index)
files = {'files': open('./user/ACT.pkl', 'rb')}
sysurl = 'http://127.0.0.1:5000'
url = sysurl + '/applykey'

pk = 123
# 把ACT转为json再传

response = requests.post(url=url, files=files, data={'ACTu': json.dumps(ACT.u), 'pk': pk})
di = response.json()

# print('user get deckey:', di)

# for index in range(len(di)-1):
#
#     #1.change type to element
#     #2.calc use ele
#     #3.dec by sk
#     print(di[index][0])
#     #di[index][0] = int(di[index][0],16)/pk
#     di[index][0]
#     print(di[index][0])
#     di[index][0]= Element(pairing,G1,value=di[index][0])
#     print('1')


print('D:', di)

PK = eval(open(os.path.dirname(__file__) + '/../sys/PK.txt').read())
Y = PK['Y']

M=Element.from_hash(pairing,GT,'123')

E = Enc(M, [2, 4], PK,  pairing)


Ys = DEC(E, di, ACT, pairing)
print('M:',M)
print('E:',E)
print('Ys',Ys)
eM = E[1].__mul__(Ys.__pow__(-1))
print(eM)